/*************************************************************************
    > File Name: word_count.c
    > Author: Xing.Dai
    > Mail: xing.dai@aliyun.com 
    > Created Time: Mon 23 Mar 2015 07:27:19 AM PDT
 ************************************************************************/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>

#define DEVICE_NAME "wordcount"

static unsigned char mem[1000];	// Kernel mem data.
static char read_flag = 'y';
static int written_count = 0;

static ssize_t word_count_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
	// No read device file, begin to read.
	if(read_flag == 'n')
	{
		// Copy kernel space data to user space data.
		copy_to_user(buf, (void *)mem, written_count);
		printk("read count: %d", (int)written_count);
		read_flag = 'y';
		return written_count;
	}
	else
	{
		return 0;
	}
}

static ssize_t word_count_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
	copy_from_user(mem, buf, count);
	read_flag = 'n';
	written_count = count;
	printk("written count:%d", (int)count);
	return count;
}

static struct file_operations dev_fops = 
{
	.owner = THIS_MODULE,
	.read = word_count_read,
	.write = word_count_write,
};

static struct miscdevice misc = 
{
	.minor = MISC_DYNAMIC_MINOR,
	.name = DEVICE_NAME,
	.fops = &dev_fops,
};


// init Linux driver.
static int word_count_init(void)
{
	int ret;
	
	ret = misc_register(&misc);
	printk("word_count_init_suscess.\n");
	return 0;
}

static void word_count_exit(void)
{
	misc_deregister(&misc);
	printk("word_count_init_exit_success.\n");

}

module_init(word_count_init);
module_exit(word_count_exit);

MODULE_AUTHOR("Xing.Dai");
MODULE_DESCRIPTION("statistics of word count.");
MODULE_ALIAS("word count modules.");
MODULE_LICENSE("GPL");



